package com.cgs.query.monitor

import com.cgs.query.connection.ConnectionFactory
import com.cgs.query.metrics.ServerDataSourceMetrics.INSTANCE
import com.codahale.metrics.MetricFilter
import mu.KotlinLogging
import org.springframework.beans.factory.InitializingBean
import org.springframework.beans.factory.annotation.Autowired
private val logger = KotlinLogging.logger { }

/**
 * 监控数据源
 */
class DataSourceMonitor : MonitorBean<SourceMonitorObj, SourceMonitorInfo>, InitializingBean {

    override fun afterPropertiesSet() {
        start()
    }

    @Autowired
    private lateinit var connectionFactory: ConnectionFactory

    override fun start() {
        connectionFactory.setMetricRegistry(INSTANCE.registry)
        logger.info { ">>>>>>>>>>>>>>>>开启数据源监控" }
    }

    override fun stop() {
        logger.info { ">>>>>>>>>>>>>>>>关闭数据源监控" }
    }

    /**
     * $poolName.pool.
     */
    override fun monitor(obj: SourceMonitorObj): SourceMonitorInfo? {
        val filter = MetricFilter { name, _ -> name?.startsWith("${obj.sourceId}.pool") == true }
        val length = "${obj.sourceId}.pool.".length
        val timers = INSTANCE.registry.getTimers(filter)
        val timerInfo = timers.map {
            val t = it.value
            mapOf(
                    "count" to t.count,
                    "fifteenMinuteRate" to t.fifteenMinuteRate,
                    "fiveMinuteRate" to t.fiveMinuteRate,
                    "oneMinuteRate" to t.oneMinuteRate,
                    "meanRate" to t.meanRate
            )
        }
        val gauges = INSTANCE.registry.getGauges(filter)
        val gaugeInfo = gauges.map {
            mapOf(getName(length, it.key) to it.value.value)
        }
        val histograms = INSTANCE.registry.getHistograms(filter)
        val histogramInfo = histograms.map {
            mapOf(getName(length, it.key) to it.value.count)
        }
        val meters = INSTANCE.registry.getMeters(filter)
        val meterInfo = meters.map {
            val t = it.value
            mapOf(
                    "count" to t.count,
                    "fifteenMinuteRate" to t.fifteenMinuteRate,
                    "fiveMinuteRate" to t.fiveMinuteRate,
                    "oneMinuteRate" to t.oneMinuteRate,
                    "meanRate" to t.meanRate
            )
        }
        val counters = INSTANCE.registry.getCounters(filter)
        val countersInfo = counters.map {
            mapOf(getName(length, it.key) to it.value.count)
        }
        return SourceMonitorInfo(timerInfo, gaugeInfo, histogramInfo, meterInfo, countersInfo)
    }

    private fun getName(index: Int, key: String): String {
        return key.substring(index)
    }
}

class SourceMonitorInfo(
        timerInfo: Any,
        gaugeInfo: Any,
        histogramInfo: Any,
        meterInfo: Any,
        countInfo: Any
) : MonitorInfo() {

    val info = mapOf(
            "timers" to timerInfo,
            "gauges" to gaugeInfo,
            "histograms" to histogramInfo,
            "meters" to meterInfo,
            "counts" to countInfo
    )
}

/**
 * 数据源监控对象
 */
data class SourceMonitorObj(
        /**数据源id*/
        val sourceId: String
) : MonitorObj()
